import { Col, Flex, Modal, Row, Typography } from 'antd';
import TextArea from 'antd/es/input/TextArea';
import { useEffect, useState } from 'react';

import { getP2PConnectionData, setP2PConnectionData } from '../../../../../api/walletsAPI.ts';
import { MainButton } from '../../../../../components/MainButton/MainButton.tsx';
import { HeaderText } from '../../../../../components/typography';
import { useBarterStyles } from '../styles.tsx';

import { BarterCard } from './BarterCard.tsx';

import type { MetadataList } from '../../../../../types.ts';
import type { FC } from 'react';

interface IBarterModalProps {
    isModalOpen: boolean;
    handleOk: () => void;
    handleCancel: () => void;
    modalData: { 
        initiatorAddress: string;
        receiverAddress: string; 
        isInitiator: boolean;
    };
}

type P2PDataForConnect = {
    initiatorAddress: string;
    receiverAddress: string;
    isInitiator: boolean;

}

type P2PDataForRemoteDescription = {
    peerConnection: RTCPeerConnection;
    remoteP2PData: {
        walletConnectionOffer: string;
        walletICECandidates: string;
    }
}

const iceServers = [{
    urls: [
        'stun.l.google.com:19302',
        'stun1.l.google.com:19302',
        'stun2.l.google.com:19302',
        'stun3.l.google.com:19302',
        'stun4.l.google.com:19302',
    ] },
];

const createLocalP2PSDP = async ({ initiatorAddress, receiverAddress, isInitiator }: P2PDataForConnect) => {
    const peerConnection = new RTCPeerConnection({ iceServers });

    let dataChannel;

    peerConnection.ondatachannel = event => {
        dataChannel = event.channel;
        createDataChannel(dataChannel);
    };

    peerConnection.onconnectionstatechange = (e) => {
        console.log(e);
        console.log(peerConnection.connectionState);
    };

    const p2pReceiverData = await getP2PConnectionData({
        walletInitiator: initiatorAddress,
        walletReceiver: receiverAddress,
        isInitiator,
    });

    let remoteDescription: RTCSessionDescriptionInit | null = null;

    if (p2pReceiverData?.walletConnectionOffer) {
        remoteDescription = JSON.parse(p2pReceiverData.walletConnectionOffer);
    }

    const SDP = remoteDescription?.type !== 'offer'
        ? await createP2POffer(peerConnection, dataChannel)
        : await createP2PAnswer({ peerConnection, remoteSDP: remoteDescription });

    if (p2pReceiverData?.walletICECandidates && remoteDescription?.type === 'offer') {
        await peerConnection.addIceCandidate(JSON.parse(p2pReceiverData.walletICECandidates));
    }

    const ICECandidateString = await getICECandidate(peerConnection);

    console.log({ dataChannel, SDP });

    await setP2PConnectionData({
        walletInitiator: initiatorAddress,
        walletReceiver: receiverAddress,
        walletConnectionOffer: SDP,
        walletICECandidates: ICECandidateString,
        isInitiator,
    });
    if (p2pReceiverData && remoteDescription?.type !== 'offer') {
        await setP2PConnectionData({
            walletInitiator: initiatorAddress,
            walletReceiver: receiverAddress,
            walletConnectionOffer: '',
            walletICECandidates: '',
            isInitiator: !isInitiator,
        });
    }

    return peerConnection;
};

const createP2POffer = async (peerConnection: RTCPeerConnection, dataChannel: RTCDataChannel | undefined) => {
    dataChannel = peerConnection.createDataChannel('chat');
    createDataChannel(dataChannel);
    const offer = await peerConnection.createOffer();
    await peerConnection.setLocalDescription(offer);
    return JSON.stringify(offer);
};

const createP2PAnswer = async ({ peerConnection, remoteSDP }: {peerConnection: RTCPeerConnection; remoteSDP: RTCSessionDescriptionInit}) => {
    await peerConnection.setRemoteDescription(remoteSDP);
    const answer = await peerConnection.createAnswer();
    await peerConnection.setLocalDescription(answer);
    return JSON.stringify(answer);
};

const getICECandidate = (peerConnection: RTCPeerConnection): Promise<string> => {
    return new Promise(resolve => {
        peerConnection.onicecandidate = event => {
            if (event.candidate) {
                resolve(JSON.stringify(event.candidate));
            }
        };
    });
};

const getRemoteP2PData = async ({ initiatorAddress, receiverAddress, isInitiator }: P2PDataForConnect) => {
    return await getP2PConnectionData({
        walletInitiator: initiatorAddress,
        walletReceiver: receiverAddress,
        isInitiator,
    });
};

const setRemoteP2PDescription = async ({ peerConnection, remoteP2PData }: P2PDataForRemoteDescription) => {
    await peerConnection.setRemoteDescription(JSON.parse(remoteP2PData.walletConnectionOffer));
    await peerConnection.addIceCandidate(JSON.parse(remoteP2PData.walletICECandidates));
};

const createDataChannel = (dataChannel: RTCDataChannel) => {
    dataChannel.onopen = () => console.log('DataChannel opened');
    dataChannel.onclose = () => console.log('DataChannel closed');
    dataChannel.onmessage = event => {
        const messages = document.querySelector('#chat-text kbd') as HTMLElement;
        messages.innerHTML += 'Remote: ' + event.data + '\n';
    };

    const chatInput = document.getElementById('chat-input') as HTMLTextAreaElement;

    if (chatInput) {
        chatInput.onkeydown = (e) => {
            if (e.key === 'Enter') {

                const message = chatInput.value;
                dataChannel.send(message);
                const messages = document.querySelector('#chat-text kbd') as HTMLElement;
                messages.innerHTML += 'You: ' + message + '\n';
                chatInput.value = '';
            }
        };
    }
};

export const BarterTradeModal:FC<IBarterModalProps> = ({
    isModalOpen,
    handleOk,
    handleCancel,
    modalData,
}) => {

    const { styles } = useBarterStyles();
    const [yourNFTs] = useState<MetadataList>([]);
    const [otherNFTs] = useState<MetadataList>([]);
    
    useEffect(() => {
        let intervalId: NodeJS.Timeout;
        const p2pConnect = async () => {
            const p2pDataForConnect = {
                initiatorAddress: modalData.initiatorAddress,
                receiverAddress: modalData.receiverAddress,
                isInitiator: modalData.isInitiator,
            };
            const peerConnection = await createLocalP2PSDP(p2pDataForConnect);

            let remoteP2PData = await getRemoteP2PData(p2pDataForConnect);

            intervalId = setInterval(async () => {
                if (peerConnection.signalingState !== 'stable') {
                    console.log('ping', peerConnection.signalingState);
                    remoteP2PData = await getRemoteP2PData(p2pDataForConnect);
                    if (remoteP2PData?.walletConnectionOffer) {
                        if (remoteP2PData.walletConnectionOffer && peerConnection.localDescription?.type === 'offer') {
                            await setRemoteP2PDescription({ peerConnection, remoteP2PData });
                        }
                    }
                } else {
                    clearInterval(intervalId);

                }
            }, 5000);

        };

        isModalOpen && void p2pConnect();
        return () => clearInterval(intervalId);
    }, [isModalOpen, modalData]);

    return (
        <Modal
            className={styles.modal}
            open={isModalOpen}
            onCancel={handleCancel}
            okButtonProps={{ style: { display: 'none' } }}
            cancelButtonProps={{ style: { display: 'none' } }}
        >
            <Row>
                <Col span={24}>
                    <Flex justify="center">
                        <HeaderText>
                        Обмен NFT
                        </HeaderText>
                    </Flex>
                </Col>
            </Row>
            <Row gutter={16}>
                <Col span={12}>
                    <BarterCard listOfNFTs={yourNFTs} text="Ваше предложение"/>
                </Col>
                <Col span={12}>
                    <BarterCard listOfNFTs={otherNFTs} text="NFT пользователя"/>
                </Col>
            </Row>
            <TextArea
                id="chat-input"
                placeholder="Autosize height with minimum and maximum number of lines"
                autoSize={{ minRows: 2, maxRows: 6 }}
            />
            <Typography.Text id="chat-text" keyboard>Zdarova</Typography.Text>

            <Col span={24}>
                <Flex justify="center">
                 
                    <MainButton onClick={async () => {
                        handleOk();
                    }}
                    disabled={false}
                    >
                                    Отправить предложение
                    </MainButton>

                </Flex>
            </Col>

        </Modal>
    );
};

